/*
300M--200KB
real	0m0.425s
user	0m0.068s
sys		0m0.332s

300M--10KB
real	0m1.551s
user	0m0.128s
sys		0m0.840s

1G--200KB
real	0m3.602s
user	0m0.392s
sys		0m1.932s

按需读取，每次需要的时候就读取，没有预读功能	
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>

#include "project.h"

static size_t atom_read(FILE*,char*,size_t);
static char * concat_path_name(const char*);
extern int get_file_size(const char*);
void f_read(char**,int);

char f_buf[BLOCK_SIZE];
FILE *f_fp = NULL;

int
main (int argc, char *argv[])
{
	int size = get_file_size(argv[1]);
	if (size <= 0)
	{
		fprintf(stderr, "file not exists\n");
		exit(-1);
	}

	char *str;
	for (;;)
	{
		f_read(&str,0);
		// 文件读取完毕，继续执行下一次查询，这里先模拟一次
		if (str[0] == '\0')
		{
			f_read(&str, 1);
			return 0;
		}
		//printf("%s\n", str);
	}

	return 0;
}

/**
 * find out whether f_name exists
 * -1 	NOT EXIST
 * 0 	EXIST BUT SIZE IS 0
 * >0	SIZE
 */
int
get_file_size (const char *f_name)
{
	char *full_name = concat_path_name(f_name);

	if (access(full_name, F_OK) != 0)
	{
		free(full_name);
		return -1;
	}
	else
	{
		struct stat st;
		(void)lstat(full_name, &st);

		f_fp = fopen(full_name, "r");
		if (f_fp == NULL)
		{
			fprintf(stderr, "open file error");
			exit(-1);
		}

		free(full_name);
		return st.st_size;
	}
}

/**
 * @param flag whether send action ends; when it ends, we can "release" memory
 */
void
f_read (char **buf, int flag)
{
	if (flag == 1)
	{
		memset(f_buf, '\0', BLOCK_SIZE);
		fclose(f_fp);
		return;
	}

	int i = atom_read(f_fp, f_buf, BLOCK_SIZE);
	*(f_buf + i) = '\0';
	*buf = f_buf;
}

/**
 * read from fp to buf in atom
 */
static size_t
atom_read (FILE *fp, char *buf, size_t count)
{
	size_t need = count, got;
	while ((got = fread(buf, sizeof(char), need, fp)) > 0 && (need -= got) > 0)
		buf += got;

	return (got < 0 ? got : (count - need));
}

static char *
concat_path_name (const char *f_name)
{
	char *full_name = (char*)malloc(FILENAME_LENGTH);
	/*第一次分配内存失败，等待3秒再申请一次*/
	if (full_name == NULL)
	{
		sleep(3);
		full_name = (char*)malloc(FILENAME_LENGTH);
		if (full_name == NULL)
		{
			fprintf(stderr, "Error: alloc Memory error");
			exit(-1);
		}
	}

	snprintf(full_name, FILENAME_LENGTH, "%s%s", FILEPATH, f_name);

	return full_name;
}